/******************************************************************************
 * (C) Copyright 2013 Atech-Automotive
 * FILE NAME:    hwa_e2.c
 * DESCRIPTION:
 * 
 * DATE BEGUN:   2014/08/06
 * BY:                         
 * PRODUCT NAME:
 * APPLICATION:
 * TARGET H/W:
 * DOC REF:
 *****************************************************************************
 */

/*****************************************************************************
** #include 
*****************************************************************************/
#include <string.h>
#include "system.h"
#include "hwa_e2.h"
#include "hwa_e2_Cfg.h"

#include "driver_e2.h"
#include "hwa_e2_callback.h"

/*****************************************************************************
** #define
*****************************************************************************/
/*E2 Each ID Data Lrc Storage structure*/
/* in total  8 bytes    byte[0]~byte[3]:data,   
                        byte[4]~byte[5]:lrc, 
                        byte[6]~byte[7]:0xFF */
#define E2_TOTAL_DATA_STORAGE_LEN  ((UINT8)8) 
#define E2_DATA_LEN                ((UINT8)4) 
#define E2_LRC_LEN                 ((UINT8)2) 
#define E2_DATAANDLRC_LEN          ((UINT8)6) 
#define E2_SECTOR_DATA_LEN         ((UINT8)4) 

/* s12g128 eeprom data area 0x400~0x13FF */
/* normal data area 0x400~0xBFF */
/* backup data area 0xC00~0x13FF */
#define E2_DEFAULT_VALUE  (0xFF)

/*****************************************************************************
** typedef
*****************************************************************************/


/* ee data struct */
typedef struct 
{
    E2_Request_E e2_request;
    UINT8   e2_status;
    
} E2_DATA_STRUCT;

typedef struct 
{
    UINT32* e2_write_memcpy_ptr;
    UINT32* e2_write_lrc_memcpy_ptr;    
    UINT32* e2_write_backup_memcpy_ptr;
    UINT32* e2_write_lrc_backup_memcpy_ptr; 
    
} E2_DATA_CONST_STRUCT;

typedef enum
{
    CMD_Start_Sample = 0,
    CMD_Stop_Sample,
    
} E2_Cmd_E;

/*****************************************************************************
** global variable
*****************************************************************************/
UINT32 g_u32_write_e2_data[NUM_OF_E2_ID];
UINT32 g_u32_write_e2_backup_data[NUM_OF_E2_ID];
UINT32 g_u32_write_lrc_e2_data[NUM_OF_E2_ID];
UINT32 g_u32_write_lrc_e2_backup_data[NUM_OF_E2_ID];   

UINT32 u32_e2_read_memcpy;
UINT32 u32_e2_read_lrc_memcpy; 
UINT32 u32_e2_read_backup_memcpy;
UINT32 u32_e2_read_lrc_backup_memcpy;  

/*****************************************************************************
** static variables
*****************************************************************************/
static E2_Cmd_E s_stop_sample  = CMD_Start_Sample;
static BOOL s_b_reading_flag = FALSE;

static const E2_DATA_CONST_STRUCT c_e2_data[] = 
{
    E2_DATA_CONST_TABLE
};

static E2_DATA_STRUCT e2_data[] = 
{
   E2_DATA_TABLE
       	
}; 

/*****************************************************************************
** static constants
*****************************************************************************/
const UINT16 eeMap[NUM_OF_E2_ID] =
{
   /* address */
     EE_MAP_TABLE     
};  

/* backup area address and length */
const UINT16 eebackupMap[NUM_OF_E2_ID] =
{
   /* address */
     EE_BACKUP_MAP_TABLE     
};

/*****************************************************************************
** static function prototypes
*****************************************************************************/
static UINT16 hwa_e2CalculateLrc( UINT8 *data_buf, UINT8 len );
static void hwa_e2WriteNormalArea( UINT8 index, UINT8* pStatus );
static void hwa_e2WriteBackupArea(UINT8 index, UINT8 *pStatus);
static void hwa_e2ReadNormalBackupArea( UINT8 index, UINT8 *pStatus ); 
static void hwa_e2EraseNormalBackupArea( UINT8 idx, UINT16 addr, UINT8* pstatus );
static void hwa_e2InitNormalArea( UINT8 index, UINT8 *pStatus );
static void hwa_e2InitBackupArea( UINT8 index, UINT8 *pStatus );

/*****************************************************************************
** function prototypes
*****************************************************************************/


/****************************************************************************/
/**
 * Function Name: hwa_e2Init
 * Description: Initialize EEPROM module
 *
 * Param:   none
 * Return:  none
 * Author:  2014/02/24,                 
 ****************************************************************************/
void hwa_e2Init( void ) 
{
    Driver_E2Init();
}

/****************************************************************************/
/**
 * Function Name: hwa_e2ReadDataById
 * Description: Sending request to E2 scheduler for read.
 *              Don't invoked this function in interrupt.
 *
 * Param arg1 data_id_U8: Request data id
 *
 * Return:  TRUE  - ID is idle, set read request.
 *          FALSE - ID is busy, don't set the read request. 
 * Author:  2014/02/24,                 
 ****************************************************************************/
BOOL hwa_e2ReadDataById( UINT8 idx, UINT32 * p_u32_read )
{
    UINT8 e2_Status;
    UINT8 e2_backup_Status;   
    UINT16 u16_normal_lrc;
    UINT16 u16_normal_cal_lrc;
    UINT16 u16_backup_lrc;
    UINT16 u16_backup_cal_lrc;
    UINT8 u8_valid_sector = 0;
    UINT8 u8_invalid_num = 0;
    static UINT8 s_u8_read_buf[8];	

    ///////////////////////////////////////////////////

    if( (hwa_e2GetVBat() < c_u8_e2_cfg_vbat_limit_value)  
     && (ON == c_b_e2_cfg_enable_vbat_check_flag))     // if vbat >=9v,can operation eeprom
    {
        s_b_reading_flag = FALSE;
        return FALSE;
    }
    s_b_reading_flag=TRUE;		
    if( (FSTAT_CCIF) // if eeprom is not busy 
     && (E2_REQUEST_IDLE == e2_data[idx].e2_request))
    {	    
        if (idx >= NUM_OF_E2_ID) //e2 id is invalid!!
        {       
            s_b_reading_flag = FALSE;
            return FALSE;        
        }
        // read normal area data 
        Driver_E2Read( s_u8_read_buf, eeMap[idx], E2_DATA_LENGTH, &e2_Status );
        (void)memcpy( (UINT8*)(&u32_e2_read_memcpy),     
                      s_u8_read_buf,                  
                      E2_SECTOR_DATA_LEN );
        (void)memcpy( (UINT8*)(&u32_e2_read_lrc_memcpy), 
                      s_u8_read_buf + E2_SECTOR_DATA_LEN,
                      E2_SECTOR_DATA_LEN );					    

        if( e2_Status == E2_CMD_DONE ) // if read finish 
        {      
            e2_data[idx].e2_status = E2_STATUS_IDLE;
        
            //read backup area data 	
            Driver_E2Read(s_u8_read_buf, eebackupMap[idx], E2_DATA_LENGTH, &e2_backup_Status);
            (void)memcpy( (UINT8*)(&u32_e2_read_backup_memcpy),
                          s_u8_read_buf,
                          E2_SECTOR_DATA_LEN );
            (void)memcpy( (UINT8*)(&u32_e2_read_lrc_backup_memcpy),
                          s_u8_read_buf + E2_SECTOR_DATA_LEN,
                          E2_SECTOR_DATA_LEN );						 

            if( e2_backup_Status == E2_CMD_DONE ) // if read finish 
            {
                // calculate normal  and backup area lrc 
                u16_normal_cal_lrc = hwa_e2CalculateLrc( (UINT8 *)(&u32_e2_read_memcpy), E2_SECTOR_DATA_LEN );
                u16_normal_lrc     = (*((UINT8*)(&u32_e2_read_lrc_memcpy)) << 8) + (*((UINT8*)(&u32_e2_read_lrc_memcpy)+1));	

                u16_backup_cal_lrc = hwa_e2CalculateLrc( (UINT8 *)(&u32_e2_read_backup_memcpy), E2_SECTOR_DATA_LEN );	
                u16_backup_lrc     = (*((UINT8*)(&u32_e2_read_lrc_backup_memcpy)) << 8) + (*((UINT8*)(&u32_e2_read_lrc_backup_memcpy)+1));	

                if( u16_normal_cal_lrc == u16_normal_lrc )
                {
                    u8_valid_sector = 1;
                }
                else
                {
                    u8_invalid_num++;
                }

                if( u16_backup_cal_lrc == u16_backup_lrc )
                {
                    u8_valid_sector = 2;
                }
                else
                {
                    u8_invalid_num++;
                }	
                
                if( u8_invalid_num == 2 ) // if all lrc are invalid 
                {		
                    if (  (u32_e2_read_memcpy            == 0xFFFFFFFF ) 
                       && (u32_e2_read_backup_memcpy     == 0xFFFFFFFF ) 
                       && (u32_e2_read_lrc_memcpy        == 0xFFFFFFFF ) 
                       && (u32_e2_read_lrc_backup_memcpy == 0xFFFFFFFF )  
                       )
                    {
                        s_b_reading_flag = FALSE;
                        *p_u32_read = u32_e2_read_memcpy;
                        return TRUE;
                    }
                    else
                    {
                        e2_data[idx].e2_request = E2_REQUEST_INIT;  
                        
                        s_b_reading_flag = FALSE;                    
                        return FALSE;
                    }					
                }
                else if( u8_invalid_num == 1 ) // if only one  lrc is invalid 
                {
                    // if valid lrc is normal area 
                    if( u8_valid_sector == 1 ) 
                    {
                        // recover backup area and backup right data 
                        e2_data[idx].e2_request = E2_REQUEST_RECOVER_BACKUP; 

                        (void)memcpy((UINT8*)(&u32_e2_read_backup_memcpy),                   (UINT8*)(&u32_e2_read_memcpy),     E2_SECTOR_DATA_LEN);
                        (void)memcpy((UINT8*)(&u32_e2_read_lrc_backup_memcpy),               (UINT8*)(&u32_e2_read_lrc_memcpy), E2_SECTOR_DATA_LEN);										  
                        (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_memcpy_ptr),           (UINT8*)(&u32_e2_read_memcpy),     E2_SECTOR_DATA_LEN);
                        (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_lrc_memcpy_ptr),       (UINT8*)(&u32_e2_read_lrc_memcpy), E2_SECTOR_DATA_LEN);								  
                        (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_backup_memcpy_ptr),    (UINT8*)(&u32_e2_read_memcpy),     E2_SECTOR_DATA_LEN);	
                        (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_lrc_backup_memcpy_ptr),(UINT8*)(&u32_e2_read_lrc_memcpy), E2_SECTOR_DATA_LEN);
                        
                    }
                    else // if valid lrc is backup area 
                    {
                        // recover normal area and backup right data 
                        e2_data[idx].e2_request = E2_REQUEST_RECOVER_NORMAL;  			

                        (void)memcpy((UINT8*)(&u32_e2_read_memcpy),                          (UINT8*)(&u32_e2_read_backup_memcpy),     E2_SECTOR_DATA_LEN);
                        (void)memcpy((UINT8*)(&u32_e2_read_lrc_memcpy),                      (UINT8*)(&u32_e2_read_lrc_backup_memcpy), E2_SECTOR_DATA_LEN);										  
                        (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_memcpy_ptr),           (UINT8*)(&u32_e2_read_memcpy),            E2_SECTOR_DATA_LEN);
                        (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_lrc_memcpy_ptr),       (UINT8*)(&u32_e2_read_lrc_memcpy),        E2_SECTOR_DATA_LEN);								  
                        (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_backup_memcpy_ptr),    (UINT8*)(&u32_e2_read_memcpy),            E2_SECTOR_DATA_LEN);	
                        (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_lrc_backup_memcpy_ptr),(UINT8*)(&u32_e2_read_lrc_memcpy),        E2_SECTOR_DATA_LEN);								  
                    }
                }
                s_b_reading_flag = FALSE;
                *p_u32_read = u32_e2_read_memcpy;
                return TRUE;
            }
            else
            {
                s_b_reading_flag = FALSE;
                return FALSE;
            }
        }
        else
        {
            s_b_reading_flag = FALSE;
            return FALSE;
        }
    }
    else
    {
        s_b_reading_flag = FALSE;
        return FALSE;
    }
    
}

/****************************************************************************/
/**
 * Function Name: hwa_e2WriteDataById
 * Description: Sending request to E2 scheduler for write or write and read
 *
 * Param arg1 data_id_U8: Request data id
 *       arg2 data_ptr: Pointer of write data
 *
 * Return:  TRUE:  ID is idle, set write request.
 *          FALSE: ID is busy, don't set the write request. 
 * Author:  2014/02/24,                 
 ****************************************************************************/
BOOL hwa_e2WriteDataById( UINT8 idx, UINT32 u32_wr_data )
{ 
    UINT16 u16_normal_lrc = 0; 

    //////////////////////////////////////

    if( (hwa_e2GetVBat() < c_u8_e2_cfg_vbat_limit_value) /* if vbat >=9v,can operation eeprom */
     && (ON == c_b_e2_cfg_enable_vbat_check_flag)
      )
    {
        s_b_reading_flag = FALSE;
        return FALSE;
    }
		   
    if ( idx >= NUM_OF_E2_ID ) /* e2 id is invalid!! */
    {       
        return FALSE;      
    }
    else
    {			 
        /* if it is not busy, set write action request */
        if ( e2_data[idx].e2_request == E2_REQUEST_IDLE )
        {
            e2_data[idx].e2_status = E2_STATUS_IDLE;
        
            /* copy data , calculate lrc,the last two bytes set 0xFF */
            (void)memcpy( (UINT8 *)c_e2_data[idx].e2_write_memcpy_ptr,        (UINT8 *)&u32_wr_data, 4U);
            (void)memcpy( (UINT8 *)c_e2_data[idx].e2_write_backup_memcpy_ptr, (UINT8 *)&u32_wr_data, 4U);			
            u16_normal_lrc = hwa_e2CalculateLrc( (UINT8 *)c_e2_data[idx].e2_write_memcpy_ptr, E2_SECTOR_DATA_LEN ); 

            *((UINT8*)(c_e2_data[idx].e2_write_lrc_memcpy_ptr))          = (UINT8)((u16_normal_lrc>>8) &0x00FF);	
            *((UINT8*)(c_e2_data[idx].e2_write_lrc_memcpy_ptr)+1)        = (UINT8)(u16_normal_lrc &0x00FF);							  
            *((UINT8*)(c_e2_data[idx].e2_write_lrc_backup_memcpy_ptr))   = (UINT8)((u16_normal_lrc>>8) &0x00FF);	
            *((UINT8*)(c_e2_data[idx].e2_write_lrc_backup_memcpy_ptr)+1) = (UINT8)(u16_normal_lrc &0x00FF);						  
            (void)memset( (UINT8*)(c_e2_data[idx].e2_write_lrc_memcpy_ptr) + E2_LRC_LEN,E2_DEFAULT_VALUE,
                          (E2_TOTAL_DATA_STORAGE_LEN - E2_DATAANDLRC_LEN) );
            (void)memset( (UINT8*)(c_e2_data[idx].e2_write_lrc_backup_memcpy_ptr) + E2_LRC_LEN,E2_DEFAULT_VALUE,
                          (E2_TOTAL_DATA_STORAGE_LEN - E2_DATAANDLRC_LEN) );			   	       

            e2_data[idx].e2_request = E2_REQUEST_WR;			
            return TRUE;
        }
        else /* it is busy or read action not completed! */    
        {
            return FALSE;
        }
    }
}  

/****************************************************************************/
/**
 * Function Name: hwa_e2GetRequest
 * Description: Return the request of E2
 *
 * Param arg1 idx: Request data id
 *
 * Return:  E2_REQUEST_IDLE		         ((UINT8)0)
 *          E2_REQUEST_WR  	             ((UINT8)1)
 *          E2_REQUEST_RD	  	         ((UINT8)2)
 *          E2_REQUEST_RECOVER_NORMAL  	 ((UINT8)3)
 *          E2_REQUEST_RECOVER_BACKUP	 ((UINT8)4)  
 * Author:  2016/03/31,                 
 ****************************************************************************/
E2_Request_E hwa_e2GetRequest( UINT8 idx )
{
    return((UINT8)(e2_data[idx].e2_request));
}  

/****************************************************************************/
/**
 * Function Name: hwa_e2WriteNormalArea
 * Description: Write normal area
 *
 * Param arg1 index: Request data id
 *       arg2 pStatus: Pointer of command status
 *                     E2_CMD_STARTED - Operation is Starting
 *                     E2_ERROR_ARG   - Operation is Error
 *
 * Return:  none
 * Author:  2014/02/24,                 
 ****************************************************************************/
static void hwa_e2WriteNormalArea( UINT8 index, UINT8* pStatus ) 
{
    UINT16 u16_normal_lrc;
    UINT16 u16_normal_cal_lrc;
    UINT16 u16_backup_lrc;
    UINT16 u16_backup_cal_lrc;
    UINT8 u8_valid_sector = 0;
    UINT8 u8_invalid_num = 0;     
    static UINT8 s_u8_data_buf[8];

    ///////////////////////////////////////////
    
    /* calculate normal and backup area lrc */      
    u16_normal_cal_lrc = hwa_e2CalculateLrc((UINT8 *)c_e2_data[index].e2_write_memcpy_ptr,        E2_SECTOR_DATA_LEN);
    u16_normal_lrc     = (*((UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr)) << 8) + (*((UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr)+1));    
    u16_backup_cal_lrc = hwa_e2CalculateLrc((UINT8 *)c_e2_data[index].e2_write_backup_memcpy_ptr, E2_SECTOR_DATA_LEN);   
    u16_backup_lrc     = (*((UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr)) << 8) + (*((UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr)+1));  

    if( u16_normal_cal_lrc == u16_normal_lrc )
    {
        u8_valid_sector = 1;
    }
    else
    {
        u8_invalid_num++;
    }
    if( u16_backup_cal_lrc == u16_backup_lrc )
    {
        u8_valid_sector = 2;
    }
    else
    {
        u8_invalid_num++;
    }  
    
    if( u8_invalid_num == 2 ) /* if all lrc are invalid */
    {           
        *pStatus = E2_ERROR_ARG;
    }
    else if( u8_invalid_num == 1 ) /* if only one  lrc is invalid */
    {
        if( u8_valid_sector == 1 ) /* if valid lrc is normal area */
        {                         
            (void)memcpy( (UINT8*)(c_e2_data[index].e2_write_backup_memcpy_ptr),     (UINT8*)(c_e2_data[index].e2_write_memcpy_ptr),     E2_SECTOR_DATA_LEN);    
            (void)memcpy( (UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr), (UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr), E2_SECTOR_DATA_LEN);                                                                  
        }
        else /* if valid lrc is backup area */
        {          
            (void)memcpy( (UINT8*)(c_e2_data[index].e2_write_memcpy_ptr),     (UINT8*)(c_e2_data[index].e2_write_backup_memcpy_ptr),     E2_SECTOR_DATA_LEN);
            (void)memcpy( (UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr), (UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr), E2_SECTOR_DATA_LEN);                                                                                            
        }
        (void)memcpy( s_u8_data_buf,                      (UINT8*)(c_e2_data[index].e2_write_memcpy_ptr),     E2_SECTOR_DATA_LEN );
        (void)memcpy( s_u8_data_buf + E2_SECTOR_DATA_LEN, (UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr), E2_SECTOR_DATA_LEN );      
        Driver_E2Write( s_u8_data_buf, eeMap[index], E2_DATA_LENGTH, pStatus );               
    }
    else /* if two lrc is valid */
    {
        (void)memcpy( s_u8_data_buf,                      (UINT8*)(c_e2_data[index].e2_write_memcpy_ptr),     E2_SECTOR_DATA_LEN );
        (void)memcpy( s_u8_data_buf + E2_SECTOR_DATA_LEN, (UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr), E2_SECTOR_DATA_LEN );      
        Driver_E2Write( s_u8_data_buf, eeMap[index], E2_DATA_LENGTH, pStatus );               
    }
}

/****************************************************************************/
/**
 * Function Name: hwa_e2WriteBackupArea
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2015/08/14,                 
 ****************************************************************************/
static void hwa_e2WriteBackupArea( UINT8 index, UINT8 *pStatus ) 
{
    UINT16 u16_normal_lrc;
    UINT16 u16_normal_cal_lrc;
    UINT16 u16_backup_lrc;
    UINT16 u16_backup_cal_lrc;
    UINT8  u8_valid_sector = 0;
    UINT8  u8_invalid_num = 0;
    static UINT8 s_u8_data_buf[8];

    //////////////////////////////////////
    
    /* calculate normal and backup area lrc */		 	
    u16_normal_cal_lrc = hwa_e2CalculateLrc((UINT8 *)c_e2_data[index].e2_write_memcpy_ptr,        E2_SECTOR_DATA_LEN);
    u16_normal_lrc     = (*((UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr)) << 8) + (*((UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr)+1));	
    u16_backup_cal_lrc = hwa_e2CalculateLrc((UINT8 *)c_e2_data[index].e2_write_backup_memcpy_ptr, E2_SECTOR_DATA_LEN);	
    u16_backup_lrc     = (*((UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr)) << 8) + (*((UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr)+1));

    if( u16_normal_cal_lrc == u16_normal_lrc )
    {
        u8_valid_sector = 1;
    }
    else
    {
        u8_invalid_num++;
    }
    
    if( u16_backup_cal_lrc == u16_backup_lrc )
    {
        u8_valid_sector = 2;
    }
    else
    {
        u8_invalid_num++;
    }	
    
    if( u8_invalid_num == 2 ) /* if all lrc are invalid */
    {			
        *pStatus = E2_ERROR_ARG;
    }
    else if( u8_invalid_num == 1 ) /* if only one  lrc is invalid */
    {
        if( u8_valid_sector == 1 ) /* if valid lrc is normal area */
        {			  
            (void)memcpy((UINT8*)(c_e2_data[index].e2_write_backup_memcpy_ptr),     (UINT8*)(c_e2_data[index].e2_write_memcpy_ptr),     E2_SECTOR_DATA_LEN);	
            (void)memcpy((UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr), (UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr), E2_SECTOR_DATA_LEN);											  					  
        }
        else /* if valid lrc is backup area */
        {			
            (void)memcpy((UINT8*)(c_e2_data[index].e2_write_memcpy_ptr),     (UINT8*)(c_e2_data[index].e2_write_backup_memcpy_ptr),     E2_SECTOR_DATA_LEN);
            (void)memcpy((UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr), (UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr), E2_SECTOR_DATA_LEN);										  										   					
        }
        (void)memcpy(s_u8_data_buf,                      (UINT8*)(c_e2_data[index].e2_write_backup_memcpy_ptr),     E2_SECTOR_DATA_LEN);
        (void)memcpy(s_u8_data_buf + E2_SECTOR_DATA_LEN, (UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr), E2_SECTOR_DATA_LEN);	
        Driver_E2Write(s_u8_data_buf, eebackupMap[index], E2_DATA_LENGTH, pStatus);			
    }
    else /* if two lrc is valid */
    {
        (void)memcpy(s_u8_data_buf,                      (UINT8*)(c_e2_data[index].e2_write_backup_memcpy_ptr),     E2_SECTOR_DATA_LEN);
        (void)memcpy(s_u8_data_buf + E2_SECTOR_DATA_LEN, (UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr), E2_SECTOR_DATA_LEN);	
        Driver_E2Write(s_u8_data_buf, eebackupMap[index], E2_DATA_LENGTH, pStatus);				
    }
}

/****************************************************************************/
/**
 * Function Name: hwa_e2ReadNormalBackupArea
 * Description: Read normal and backup area.
 *
 * Param arg1 index: request data id
 *       arg2 pStatus: Pointer of command status
 *                     E2_CMD_DONE  - Operation is OK
 *                     E2_ERROR_ARG - Operation is Error
 * Return:  none
 * Author:  2014/02/24,                 
 ****************************************************************************/
static void hwa_e2ReadNormalBackupArea( UINT8 index, UINT8 *pStatus ) 
{
    UINT8 e2_Status;
    UINT8 e2_backup_Status;   
    UINT16 u16_normal_lrc;
    UINT16 u16_normal_cal_lrc;
    UINT16 u16_backup_lrc;
    UINT16 u16_backup_cal_lrc;
    UINT8 u8_valid_sector = 0;
    UINT8 u8_invalid_num = 0;		
    static UINT8 s_u8_read_buf[8];

    /////////////////////////////////////////////////
    
    /* read normal area data */
    Driver_E2Read(s_u8_read_buf, eeMap[index], E2_DATA_LENGTH, &e2_Status);
    (void)memcpy( (UINT8*)(&u32_e2_read_memcpy),     s_u8_read_buf,                      E2_SECTOR_DATA_LEN);
    (void)memcpy( (UINT8*)(&u32_e2_read_lrc_memcpy), s_u8_read_buf + E2_SECTOR_DATA_LEN, E2_SECTOR_DATA_LEN);			

    if( e2_Status == E2_CMD_DONE ) /* if read finish */
    {
        /* read backup area data */
        Driver_E2Read(s_u8_read_buf, eebackupMap[index], E2_DATA_LENGTH, &e2_backup_Status);
        (void)memcpy( (UINT8*)(&u32_e2_read_backup_memcpy),     s_u8_read_buf,                      E2_SECTOR_DATA_LEN);
        (void)memcpy( (UINT8*)(&u32_e2_read_lrc_backup_memcpy), s_u8_read_buf + E2_SECTOR_DATA_LEN, E2_SECTOR_DATA_LEN);				    

        if( e2_backup_Status == E2_CMD_DONE ) /* if read finish */
        {
            /* calculate normal and backup area lrc */
            u16_normal_cal_lrc = hwa_e2CalculateLrc( (UINT8 *)(&u32_e2_read_memcpy),        E2_SECTOR_DATA_LEN);
            u16_normal_lrc     = (*((UINT8*)(&u32_e2_read_lrc_memcpy)) << 8) + (*((UINT8*)(&u32_e2_read_lrc_memcpy)+1));	
            u16_backup_cal_lrc = hwa_e2CalculateLrc( (UINT8 *)(&u32_e2_read_backup_memcpy), E2_SECTOR_DATA_LEN);	
            u16_backup_lrc     = (*((UINT8*)(&u32_e2_read_lrc_backup_memcpy)) << 8) + (*((UINT8*)(&u32_e2_read_lrc_backup_memcpy)+1));	

            /* compare normal and backup area lrc */
            if( u16_normal_cal_lrc == u16_normal_lrc )
            {
                u8_valid_sector = 1;
            }
            else
            {
                u8_invalid_num++;
            }
            
            if( u16_backup_cal_lrc == u16_backup_lrc )
            {
                u8_valid_sector = 2;
            }
            else
            {
                u8_invalid_num++;
            }
            
            if( u8_invalid_num == 2 ) /* if all lrc are invalid */
            {
                *pStatus = E2_ERROR_ARG;
            }
            else if( u8_invalid_num == 1 ) /* if only one lrc is invalid */
            {
                if( u8_valid_sector == 1 ) /* if valid lrc is normal area */
                {
                    /* recover backup area and backup right data */
                    e2_data[index].e2_request = E2_REQUEST_RECOVER_BACKUP;
                    
                    (void)memcpy((UINT8*)(&u32_e2_read_backup_memcpy),      (UINT8*)(&u32_e2_read_memcpy),     E2_SECTOR_DATA_LEN);
                    (void)memcpy((UINT8*)(&u32_e2_read_lrc_backup_memcpy),  (UINT8*)(&u32_e2_read_lrc_memcpy), E2_SECTOR_DATA_LEN);										  
                    (void)memcpy((UINT8*)(c_e2_data[index].e2_write_memcpy_ptr),            (UINT8*)(&u32_e2_read_memcpy),     E2_SECTOR_DATA_LEN);
                    (void)memcpy((UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr),        (UINT8*)(&u32_e2_read_lrc_memcpy), E2_SECTOR_DATA_LEN);								  
                    (void)memcpy((UINT8*)(c_e2_data[index].e2_write_backup_memcpy_ptr),     (UINT8*)(&u32_e2_read_memcpy),     E2_SECTOR_DATA_LEN);	
                    (void)memcpy((UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr), (UINT8*)(&u32_e2_read_lrc_memcpy), E2_SECTOR_DATA_LEN);											  					  
                }
                else /* if valid lrc is backup area */
                {
                    /* recover normal area and backup right data */
                    e2_data[index].e2_request = E2_REQUEST_RECOVER_NORMAL; 
                    
                    (void)memcpy((UINT8*)(&u32_e2_read_memcpy),             (UINT8*)(&u32_e2_read_backup_memcpy),     E2_SECTOR_DATA_LEN);
                    (void)memcpy((UINT8*)(&u32_e2_read_lrc_memcpy),         (UINT8*)(&u32_e2_read_lrc_backup_memcpy), E2_SECTOR_DATA_LEN);										  
                    (void)memcpy((UINT8*)(c_e2_data[index].e2_write_memcpy_ptr),            (UINT8*)(&u32_e2_read_memcpy),            E2_SECTOR_DATA_LEN);
                    (void)memcpy((UINT8*)(c_e2_data[index].e2_write_lrc_memcpy_ptr),        (UINT8*)(&u32_e2_read_lrc_memcpy),        E2_SECTOR_DATA_LEN);								  
                    (void)memcpy((UINT8*)(c_e2_data[index].e2_write_backup_memcpy_ptr),     (UINT8*)(&u32_e2_read_memcpy),            E2_SECTOR_DATA_LEN);	
                    (void)memcpy((UINT8*)(c_e2_data[index].e2_write_lrc_backup_memcpy_ptr), (UINT8*)(&u32_e2_read_lrc_memcpy),        E2_SECTOR_DATA_LEN);										   					
                }

                *pStatus = E2_CMD_DONE;	
            }
            else 
            {
                *pStatus = E2_CMD_DONE;
            }
        }
        else
        {
            *pStatus = e2_backup_Status;		    	
        }
    }
    else
    {
        *pStatus = e2_Status;
    }   
}

/****************************************************************************/
/**
 * Function Name: hwa_e2EraseNormalBackupArea
 * Description: Erase normal and backup area.
 *
 * Param arg1 idx: request id
 *       arg2 addr: Erase address
 *       arg3 pstatus: Pointer of command status
 *                     E2_CMD_STARTED - Operation is Starting
 *                     E2_ERROR_ARG   - Operation is Error
 *
 * Return:  none
 * Author:  2014/02/24,                 
 ****************************************************************************/
static void hwa_e2EraseNormalBackupArea( UINT8 idx, UINT16 addr, UINT8* pstatus )
{
    UINT16 u16_normal_lrc;
    UINT16 u16_normal_cal_lrc;
    UINT16 u16_backup_lrc;
    UINT16 u16_backup_cal_lrc;
    UINT8 u8_valid_sector = 0;
    UINT8 u8_invalid_num = 0;

    /////////////////////////////////////////////////
    
    /* calculate normal  and backup area lrc */
    u16_normal_cal_lrc = hwa_e2CalculateLrc((UINT8 *)c_e2_data[idx].e2_write_memcpy_ptr,        E2_SECTOR_DATA_LEN);
    u16_normal_lrc     = (*((UINT8*)(c_e2_data[idx].e2_write_lrc_memcpy_ptr)) << 8) + (*((UINT8*)(c_e2_data[idx].e2_write_lrc_memcpy_ptr)+1));    
    u16_backup_cal_lrc = hwa_e2CalculateLrc((UINT8 *)c_e2_data[idx].e2_write_backup_memcpy_ptr, E2_SECTOR_DATA_LEN); 
    u16_backup_lrc     = (*((UINT8*)(c_e2_data[idx].e2_write_lrc_backup_memcpy_ptr)) << 8) + (*((UINT8*)(c_e2_data[idx].e2_write_lrc_backup_memcpy_ptr)+1));

    /* compare normal and backup area lrc */
    if( u16_normal_cal_lrc == u16_normal_lrc )
    {
        u8_valid_sector = 1;
    }
    else
    {
        u8_invalid_num++;
    }
    
    if( u16_backup_cal_lrc == u16_backup_lrc )
    {
        u8_valid_sector = 2;
    }
    else
    {
        u8_invalid_num++;
    }   
    
    if( u8_invalid_num == 2 ) /* if all lrc are invalid */
    {           
        *pstatus = E2_ERROR_ARG;
    }
    else if( u8_invalid_num == 1 ) /* if only one  lrc is invalid */
    {
        if( u8_valid_sector == 1 ) /* if valid lrc is normal area */
        {
            /* recover backup area and backup right data */                    
            (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_backup_memcpy_ptr),     (UINT8*)(c_e2_data[idx].e2_write_memcpy_ptr),     E2_SECTOR_DATA_LEN);    
            (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_lrc_backup_memcpy_ptr), (UINT8*)(c_e2_data[idx].e2_write_lrc_memcpy_ptr), E2_SECTOR_DATA_LEN);                                                                  
        }
        else /* if valid lrc is backup area */
        {
            /* recover normal area and backup right data */           
            (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_memcpy_ptr),     (UINT8*)(c_e2_data[idx].e2_write_backup_memcpy_ptr),     E2_SECTOR_DATA_LEN);
            (void)memcpy((UINT8*)(c_e2_data[idx].e2_write_lrc_memcpy_ptr), (UINT8*)(c_e2_data[idx].e2_write_lrc_backup_memcpy_ptr), E2_SECTOR_DATA_LEN);                                                                         
        }
        Driver_E2EraseSector(addr, pstatus);         
    }
    else
    {
        Driver_E2EraseSector(addr, pstatus); 
    }
}

/****************************************************************************/
/**
 * Function Name: hwa_e2InitNormalArea
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2014/05/04,                 
 ****************************************************************************/
static void hwa_e2InitNormalArea( UINT8 index, UINT8 *pStatus )
{
    UINT8 e2_Status;   
    UINT16 u16_default = 0xFFFF;
    UINT16 u16_normal_cal_lrc;	
    static UINT8 s_u8_read_buf[8];
    static UINT8 s_u8_data_buf[8];

    ///////////////////////////////////////

    /* read normal area data */
    Driver_E2Read(s_u8_read_buf, (UINT16)eeMap[index], E2_DATA_LENGTH, &e2_Status);
    (void)memcpy((UINT8*)(&u32_e2_read_memcpy),s_u8_read_buf,E2_SECTOR_DATA_LEN);
    (void)memcpy((UINT8*)(&u32_e2_read_lrc_memcpy),s_u8_read_buf+E2_SECTOR_DATA_LEN,E2_SECTOR_DATA_LEN);
    if( e2_Status == E2_CMD_DONE )
    {
        (void)memset( (UINT8*)(&u32_e2_read_memcpy), 
                      E2_DEFAULT_VALUE,
                      E2_SECTOR_DATA_LEN );
    
        u16_normal_cal_lrc = hwa_e2CalculateLrc((UINT8 *)(&u32_e2_read_memcpy),E2_SECTOR_DATA_LEN);

        (void)memcpy(s_u8_data_buf,(UINT8*)(&u32_e2_read_memcpy),E2_SECTOR_DATA_LEN);
        (void)memcpy(s_u8_data_buf+E2_SECTOR_DATA_LEN,(UINT8*)(&u16_normal_cal_lrc),E2_LRC_LEN);		
        (void)memcpy(s_u8_data_buf+E2_DATAANDLRC_LEN,(UINT8*)(&u16_default),E2_TOTAL_DATA_STORAGE_LEN - E2_DATAANDLRC_LEN);
        Driver_E2Write(s_u8_data_buf, (UINT16)eeMap[index], E2_DATA_LENGTH, pStatus);  		   
    }
    else
    {
        *pStatus = e2_Status;
    }   
}

/****************************************************************************/
/**
 * Function Name: hwa_e2InitBackupArea
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2014/05/04,                 
 ****************************************************************************/
static void hwa_e2InitBackupArea( UINT8 index, UINT8 *pStatus )
{
    UINT8 e2_Status;   
    UINT16 u16_default = 0xFFFF;
    UINT16 u16_normal_cal_lrc;	
    static UINT8 s_u8_read_buf[8];
    static UINT8 s_u8_data_buf[8];

    ///////////////////////////////////////

    /* read normal area data */
    Driver_E2Read(s_u8_read_buf, (UINT16)eebackupMap[index], E2_DATA_LENGTH, &e2_Status);
    (void)memcpy((UINT8*)(&u32_e2_read_backup_memcpy),s_u8_read_buf,E2_SECTOR_DATA_LEN);
    (void)memcpy((UINT8*)(&u32_e2_read_lrc_backup_memcpy),s_u8_read_buf+E2_SECTOR_DATA_LEN,E2_SECTOR_DATA_LEN);
    if( e2_Status == E2_CMD_DONE )
    {
        (void)memset( (UINT8*)(&u32_e2_read_backup_memcpy), 
                      E2_DEFAULT_VALUE,
                      E2_SECTOR_DATA_LEN );
    
        u16_normal_cal_lrc = hwa_e2CalculateLrc((UINT8 *)(&u32_e2_read_backup_memcpy),E2_SECTOR_DATA_LEN);

        (void)memcpy(s_u8_data_buf,(UINT8*)(&u32_e2_read_backup_memcpy),E2_SECTOR_DATA_LEN);
        (void)memcpy(s_u8_data_buf+E2_SECTOR_DATA_LEN,(UINT8*)(&u16_normal_cal_lrc),E2_LRC_LEN);		
        (void)memcpy(s_u8_data_buf+E2_DATAANDLRC_LEN,(UINT8*)(&u16_default),E2_TOTAL_DATA_STORAGE_LEN - E2_DATAANDLRC_LEN);
        Driver_E2Write(s_u8_data_buf, (UINT16)eebackupMap[index], E2_DATA_LENGTH, pStatus);  		   
    }
    else
    {
        *pStatus = e2_Status;
    }   
}

/****************************************************************************/
/**
 * Function Name: hwa_e2Handler1ms
 * Description: Runs unified state machine for e2 read and write	
 *
 * Param:   none
 * Return:  none
 * Author:  2014/02/24,                 
 ****************************************************************************/
/* ee state status */
typedef enum 
{
    E2_STATE_WR_NORMAL = 1U,
    E2_STATE_WR_NORMAL_WAIT,
    E2_STATE_WR_BACKUP,
    E2_STATE_WR_BACKUP_WAIT,
    E2_STATE_WR_NEXT,
    E2_STATE_RD,
    E2_STATE_RD_WAIT,
    E2_STATE_DEL_NORMAL_FIRST_SECTOR,
    E2_STATE_DEL_NORMAL_FIRST_SECTOR_WAIT,
    E2_STATE_DEL_NORMAL_SECOND_SECTOR,
    E2_STATE_DEL_NORMAL_SECOND_SECTOR_WAIT, 
    E2_STATE_DEL_BACKUP_FIRST_SECTOR,
    E2_STATE_DEL_BACKUP_FIRST_SECTOR_WAIT,
    E2_STATE_DEL_BACKUP_SECOND_SECTOR,
    E2_STATE_DEL_BACKUP_SECOND_SECTOR_WAIT, 
    E2_STATE_DONE,
    E2_STATE_FINISH,
    E2_STATE_IDLE,
    E2_STATE_INIT_NORMAL,
    E2_STATE_INIT_NORMAL_WAIT,
    E2_STATE_INIT_BACKUP,
    E2_STATE_INIT_BACKUP_WAIT
    
} E2_FSM_Hanlder1ms_E;

void hwa_e2Handler1ms(void)
{
    static E2_FSM_Hanlder1ms_E e2_State = E2_STATE_IDLE;
    static UINT8 e2_Status;
    static UINT8 idx = 0;

    /////////////////////////////////////////
    
    if( (hwa_e2GetVBat() < c_u8_e2_cfg_vbat_limit_value) /* if vbat >=9v,can operation eeprom */
     && (ON == c_b_e2_cfg_enable_vbat_check_flag)
      )
    {
        s_b_reading_flag = FALSE;
        return;
    }

    //////////////////////////////////////////

    if( !s_b_reading_flag ) /* not reading */
    {
        switch (e2_State)
        {
        case E2_STATE_IDLE: /* e2 state is idle */                      
             if( e2_data[idx].e2_request == E2_REQUEST_IDLE )
             {       
                 idx++;
                 if (idx >= NUM_OF_E2_ID)
                 {
                     idx = 0;
                 }
                 break;
             }
             else if( e2_data[idx].e2_request == E2_REQUEST_INIT )
             {
                 e2_State = E2_STATE_INIT_NORMAL;
                 s_stop_sample = CMD_Stop_Sample;  
             }
             else if( e2_data[idx].e2_request == E2_REQUEST_RD )
             {
                 e2_State = E2_STATE_RD;
             }
             /* first erase normal area,write normal area ,second erase 
                backup area,write backup area */
             else if( e2_data[idx].e2_request == E2_REQUEST_WR ) 
             {
                 e2_State = E2_STATE_DEL_NORMAL_FIRST_SECTOR;
                 /* notify 1ms task monitor write or erase status */
                 s_stop_sample = CMD_Stop_Sample;   
             }	
             else if (e2_data[idx].e2_request == E2_REQUEST_RECOVER_NORMAL)/* first erase normal area,write normal area */
			 {   
			     e2_State = E2_STATE_DEL_NORMAL_FIRST_SECTOR;
			     s_stop_sample = CMD_Stop_Sample;   /* notify 1ms task monitor write or erase status */
			 }
			 else if (e2_data[idx].e2_request == E2_REQUEST_RECOVER_BACKUP)/* first  erase backup area,write backup area */
			 {
			     e2_State = E2_STATE_DEL_BACKUP_FIRST_SECTOR;
			     s_stop_sample = CMD_Stop_Sample;   /* notify 1ms task monitor write or erase status */
			 }	
             else
             {
                 /* do nothing */
             }
             break;
                
        case E2_STATE_WR_NORMAL: /* write normal area */
             hwa_e2WriteNormalArea(idx, &e2_Status);
             /* if status is start write and write is not finish,
                enter into write wait */
             if( e2_Status == E2_CMD_STARTED ) 
             {
                 e2_State = E2_STATE_WR_NORMAL_WAIT;
             } 
             /* if status is write finish */
             else if (e2_Status == E2_CMD_DONE) 
             {
                 /* if is request wr normal and backup area */
                 if (e2_data[idx].e2_request == E2_REQUEST_WR)
			    {
			        e2_State = E2_STATE_DEL_BACKUP_FIRST_SECTOR;
			    }
			    else//if is request recover normal area
			    {
				    e2_State                = E2_STATE_IDLE;
					e2_data[idx].e2_status  = E2_STATUS_WR_DONE;
				 	e2_data[idx].e2_request = E2_REQUEST_IDLE;					   
				}					            
             }
             else /* if status is error */
             {  
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   /* QUIT */
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	
             }
             break;

        case E2_STATE_WR_NORMAL_WAIT: /* write normal area wait */
             if ( e2_Status == E2_CMD_DONE ) /* if status is write finish */
             {
                 /* if is request wr normal and backup area */
                 if (e2_data[idx].e2_request == E2_REQUEST_WR)
			    {
			        e2_State = E2_STATE_DEL_BACKUP_FIRST_SECTOR;
			    }
			    else//if is request recover normal area
			    {
				    e2_State                = E2_STATE_IDLE;
					e2_data[idx].e2_status  = E2_STATUS_WR_DONE;
				 	e2_data[idx].e2_request = E2_REQUEST_IDLE;					   
				}	
             }
             else if ( e2_Status == E2_TIMEOUT ) /* if status is timeout */
             { 				     
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   /* QUIT */
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	
             }
             else /* write wait */
             {
                 /* do nothing */
             }
             break;
                
             /* write backup area */
        case E2_STATE_WR_BACKUP: 					
			 hwa_e2WriteBackupArea(idx, &e2_Status);		
		
			 if(e2_Status == E2_CMD_STARTED)
		     {
		         e2_State = E2_STATE_WR_BACKUP_WAIT;
		     } 
		     else if (e2_Status == E2_CMD_DONE) 
		     {
			     e2_State = E2_STATE_IDLE;
				e2_data[idx].e2_status = E2_STATUS_WR_DONE;
			 	e2_data[idx].e2_request= E2_REQUEST_IDLE;         
		     }
		     else 
		     { 
		         e2_data[idx].e2_status = E2_STATUS_ERROR;
			    e2_State = E2_STATE_IDLE;   // QUIT 
				e2_data[idx].e2_request= E2_REQUEST_IDLE;	
		     }
			 break;

        case E2_STATE_WR_BACKUP_WAIT: /* write backup area wait */
             if (e2_Status == E2_CMD_DONE)
             {
                 e2_State = E2_STATE_IDLE;
                 e2_data[idx].e2_status = E2_STATUS_WR_DONE;
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;
             }
             else if (e2_Status == E2_TIMEOUT)
             { 				     
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   // QUIT 
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	
             }
             else 
             {
                 /* do nothing */
             }
             break;

            /* read normal and backup area */
        case E2_STATE_RD: 
             hwa_e2ReadNormalBackupArea(idx, &e2_Status);
             /* if status is start read and read is not finish,
                enter into read wait */
             if (e2_Status == E2_CMD_STARTED) 
             {
                 e2_State = E2_STATE_RD_WAIT;
             } 
             else if (e2_Status == E2_CMD_DONE) 	 	
             {    
                 e2_data[idx].e2_request = E2_REQUEST_IDLE;
                 e2_data[idx].e2_status  = E2_STATUS_RD_DONE;
                 e2_State = E2_STATE_IDLE;             
             } 
             else /* if status is error */
             {
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   /* QUIT */
                 e2_data[idx].e2_request = E2_REQUEST_IDLE;
             }
             break;

        case E2_STATE_RD_WAIT: /* read wait */
             if (e2_Status == E2_CMD_DONE)
             {
                 e2_data[idx].e2_request = E2_REQUEST_IDLE;								 
                 e2_data[idx].e2_status  = E2_STATUS_RD_DONE;
                 e2_State = E2_STATE_IDLE;
             }
             else if (e2_Status == E2_TIMEOUT)
             { 				     
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   /* QUIT */
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	 
             } 
             else 
             {		      
                 /* do nothing */
             }
             break;		
                
        /* erase normal first sector */
        case E2_STATE_DEL_NORMAL_FIRST_SECTOR: 
             hwa_e2EraseNormalBackupArea(idx, (UINT16)eeMap[idx], &e2_Status);		
             if(e2_Status == E2_CMD_STARTED)
             {
                 e2_State = E2_STATE_DEL_NORMAL_FIRST_SECTOR_WAIT;
             } 
             else if (e2_Status == E2_CMD_DONE) 
             {
                 e2_State = E2_STATE_WR_NORMAL;
             }
             else 
             { 		     
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   /* QUIT */
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	
                 /* do nothing, just wait, redo next time  */
             }
             break;

        /* erase normal first sector wait */
        case E2_STATE_DEL_NORMAL_FIRST_SECTOR_WAIT:
             if (e2_Status == E2_CMD_DONE)
             {
                 e2_State = E2_STATE_DEL_NORMAL_SECOND_SECTOR;
             }
             else if (e2_Status == E2_TIMEOUT)
             { 				    	              
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   /* QUIT */
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	
             }
             else 
             {
                 /* do nothing */
             }
             break;	

        /* erase normal second sector */	 	
        case E2_STATE_DEL_NORMAL_SECOND_SECTOR:
		     hwa_e2EraseNormalBackupArea(idx,(UINT16)(eeMap[idx]+E2_SECTOR_DATA_LEN),&e2_Status);				     		
			 if(e2_Status == E2_CMD_STARTED)
			 {
			     e2_State = E2_STATE_DEL_NORMAL_SECOND_SECTOR_WAIT;
			 } 
			 else if (e2_Status == E2_CMD_DONE) 
			 {
			     e2_State = E2_STATE_WR_NORMAL;                            
			 }
			 else 
			 { 
			    e2_data[idx].e2_status = E2_STATUS_ERROR;
			    e2_State = E2_STATE_IDLE;   // QUIT 
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	
			 }
			 break;			

	     /* erase normal second sector wait */
	    case E2_STATE_DEL_NORMAL_SECOND_SECTOR_WAIT:
			 if (e2_Status == E2_CMD_DONE)
			 {
		         e2_State = E2_STATE_WR_NORMAL;                            
			 }
			 else if (e2_Status == E2_TIMEOUT)
			 { 				     
			    e2_data[idx].e2_status = E2_STATUS_ERROR;
			    e2_State = E2_STATE_IDLE;   // QUIT
			    e2_data[idx].e2_request= E2_REQUEST_IDLE;	
			 }
			 else 
			 {
			    /* do nothing */ 
			 }
			 break;
			    
        /* erase backup first sector */
	    case E2_STATE_DEL_BACKUP_FIRST_SECTOR:
		     hwa_e2EraseNormalBackupArea(idx,eebackupMap[idx],&e2_Status);					     
			 if(e2_Status == E2_CMD_STARTED)
			 {
			     e2_State = E2_STATE_DEL_BACKUP_FIRST_SECTOR_WAIT;
			 } 
			 else if (e2_Status == E2_CMD_DONE) 
			 {
			    e2_State = E2_STATE_DEL_BACKUP_SECOND_SECTOR;         
			 }
			 else 
			 {  
			     e2_data[idx].e2_status = E2_STATUS_ERROR;
			    e2_State = E2_STATE_IDLE;   // QUIT 
			    e2_data[idx].e2_request= E2_REQUEST_IDLE;				                     	
			 }
			 break;				   

	    /* erase backup first sector wait */
	    case E2_STATE_DEL_BACKUP_FIRST_SECTOR_WAIT:
			 if ( e2_Status == E2_CMD_DONE )
			 {
			    e2_State = E2_STATE_DEL_BACKUP_SECOND_SECTOR;   
			 }
			 else if ( e2_Status == E2_TIMEOUT )
			 { 				     
			    e2_data[idx].e2_status  = E2_STATUS_ERROR;
			    e2_State                = E2_STATE_IDLE;   // QUIT 
			    e2_data[idx].e2_request = E2_REQUEST_IDLE;	
			 }
			 else 
			 {
			   
			 }
			 break;	

		/* erase backup second sector */
		case E2_STATE_DEL_BACKUP_SECOND_SECTOR:
		     hwa_e2EraseNormalBackupArea(idx,eebackupMap[idx]+E2_SECTOR_DATA_LEN,&e2_Status);				     	
			 if(e2_Status == E2_CMD_STARTED)
			 {
			     e2_State = E2_STATE_DEL_BACKUP_SECOND_SECTOR_WAIT;
			 } 
			 else if (e2_Status == E2_CMD_DONE) 
			 {
				e2_State = E2_STATE_WR_BACKUP;                            
	        
			 }
			 else 
			 {  
			    e2_data[idx].e2_status  = E2_STATUS_ERROR;
			    e2_State                = E2_STATE_IDLE;   // QUIT 	
			    e2_data[idx].e2_request = E2_REQUEST_IDLE;	
			 }
			 break;		

	    /* erase backup second sector wait */
	    case E2_STATE_DEL_BACKUP_SECOND_SECTOR_WAIT:
			 if (e2_Status == E2_CMD_DONE)
			 {
			     e2_State = E2_STATE_WR_BACKUP;                                  
			 }
			 else if (e2_Status == E2_TIMEOUT)
			 { 				     
                 e2_data[idx].e2_status  = E2_STATUS_ERROR;
                 e2_State                = E2_STATE_IDLE;   // QUIT 
                 e2_data[idx].e2_request = E2_REQUEST_IDLE;	
			 }
			 else 
			 {
			     /* do nothing */  
			 }
			 break;

        /* init normal e2 */
        case E2_STATE_INIT_NORMAL:
             hwa_e2InitNormalArea(idx, &e2_Status);
             if(e2_Status == E2_CMD_STARTED)
             {
                 e2_State = E2_STATE_INIT_NORMAL_WAIT; /* wait for end */
             }
             else if( e2_Status == E2_CMD_DONE )
             {
                 e2_State = E2_STATE_IDLE;   /* QUIT */
             }
             else if( e2_Status == E2_ERROR_ARG )
             {
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   /* QUIT */
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	
             }
             else
             {
                 /* do nothing */
             }
             break;

        /* wiat init normal e2 */
        case E2_STATE_INIT_NORMAL_WAIT:
             if (e2_Status == E2_CMD_DONE)
             {
                 e2_State = E2_STATE_INIT_BACKUP;                                  
             }
             else if (e2_Status == E2_TIMEOUT)
             { 				     
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   /* QUIT */
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	
             }
             else 
             {
                 /* do nothing */
             }
             break;

        case E2_STATE_INIT_BACKUP:
             hwa_e2InitBackupArea(idx, &e2_Status);
             if(e2_Status == E2_CMD_STARTED)
             {
                 e2_State = E2_STATE_INIT_BACKUP_WAIT; /* wait for end */
             }
             else if( e2_Status == E2_CMD_DONE )
             {
                 e2_State = E2_STATE_IDLE;   /* QUIT */
             }
             else if( e2_Status == E2_ERROR_ARG )
             {
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   /* QUIT */
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	
             }
             else
             {
                 /* do nothing */
             }
             break;

        case E2_STATE_INIT_BACKUP_WAIT:
             if (e2_Status == E2_CMD_DONE)
             {                           
                 e2_data[idx].e2_status = E2_STATUS_INIT_DONE;
                 e2_State = E2_STATE_IDLE;
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;
             }
             else if (e2_Status == E2_TIMEOUT)
             { 				     
                 e2_data[idx].e2_status = E2_STATUS_ERROR;
                 e2_State = E2_STATE_IDLE;   /* QUIT */
                 e2_data[idx].e2_request= E2_REQUEST_IDLE;	
             }
             else 
             {
                 /* do nothing */
             }
             break;

        default:
             e2_State = E2_STATE_IDLE;
             break;
        }

        /* if e2_state is idle  notify 1ms task stop monitor erase or 
           write status */	
        if( e2_State == E2_STATE_IDLE )
        {
            s_stop_sample = CMD_Start_Sample;
        }
        if( CMD_Stop_Sample == s_stop_sample )		
        {
            Driver_E2Monitor(); /* monitor erase or write status */
        }
    }
}

/****************************************************************************/
/**
 * Function Name: hwa_e2CalculateLrc
 * Description: Calculate eeprom data lrc
 *
 * Param arg1 data_buf: Pointer of buffer
 *       arg2 len: data length
 *
 * Return:  LRC value
 * Author:  2014/02/24,                 
 ****************************************************************************/
static UINT16 hwa_e2CalculateLrc( UINT8 *data_buf, UINT8 len )
{
    UINT8 i           = 0x00;
    UINT16 u16_data_1 = 0x00;
    UINT16 u16_data_2 = 0x00;
    UINT16 u16_lrc    = 0x00;

    ////////////////////////////////

    for(i = 0; i < len; i++)
    {
       u16_data_1 += data_buf[i];
	   u16_data_2 += u16_data_1;
    }
    u16_lrc = (UINT8)(u16_data_2 & 0x00FF);
    u16_lrc = u16_lrc << 8;
    u16_lrc |= (UINT8)(u16_data_2 >> 8);  

    return u16_lrc;
}

/*****************************************************************************
** End File
*****************************************************************************/

